package com.zgc.demo.ftzf.controller;

import com.zgc.demo.ftzf.entity.User;
import com.zgc.demo.ftzf.repository.UserRepository;
import org.reactivestreams.Subscription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.Disposable;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/webflux")
public class MonoTestController {


    public static void main(String[] args) {
        // 简单创建
//        Mono.fromSupplier(() -> "Hello").subscribe(System.out::println);
//        Mono.justOrEmpty(Optional.of("Hello")).subscribe(System.out::println);
//        Mono.create(sink -> sink.success("Hello")).subscribe(System.out::println);

        // 复杂构建，一些事件钩子。

//        Mono.create(monoSink -> {
//            monoSink.onRequest(value -> String.format("请求进来了：",value))
//                    .onDispose(() -> System.out.println("销毁了"))
//                    .success("返回的值，比如对象转json");
//        }).subscribe(System.out::println);

        Mono.from(s -> {
            s.onSubscribe(new Subscription() {
                @Override
                public void request(long n) {
                    System.out.println("请求调用了");
                }

                @Override
                public void cancel() {
                    System.out.println("请求取消了");
                }
            });
//            s.onError(new RuntimeException());
            s.onComplete();
        }).doOnCancel(() -> {
            System.out.println("请求取消了");
        }).doOnNext(s -> {
            System.out.println(String.format("输出%s",s));
        }).subscribe(System.out::println);
    }

    @Autowired
    UserRepository userRepository;

    @GetMapping("/user/{userId}")
    public Mono<User> getUser(@PathVariable Long userId) {
        return userRepository.findById(userId);
    }

    @GetMapping("/other")
    public Mono<String> getStr(@PathVariable Long userId) {
        return Mono.fromCallable(() -> "callable run ");
    }

    // ---------------------------mono 函数的常规操作---------------------------------------------

    @GetMapping("/f/fromCallable")
    public Mono<String> fromCallable() {
        // 能抛异常
        return Mono.fromCallable(()->"call fromCallable method");
    }

    @GetMapping("/f/fromSupplier")
    public Mono<String> fromSupplier() {
        // 不能抛异常
        return Mono.fromSupplier(()->"call fromSupplier method");
    }

    @GetMapping("/f/delay")
    public void delay() {
//        Mono.delay(Duration.ofSeconds(3)).doon;
    }

    // ---------------------------mono 静态的常规操作---------------------------------------------

    /**
     * 可以指定序列中包含的全部元素。创建出来的 Mono序列在发布这些元素之后会自动结束。
     * @return Mono
     */
    @GetMapping("/e/just")
    public Mono<String> just() {
        return Mono.just("");
    }

    /**
     * 创建一个不包含任何元素，只发布结束消息的序列。
     * @return Mono
     */
    @GetMapping("/e/empty")
    public Mono<Void> empty() {
        return Mono.empty();
    }

    /**
     * 创建一个不包含任何元素，只发布结束消息的序列。
     * @return Mono
     */
    @GetMapping("/e/justOrEmpty")
    public Mono<String> justOrEmpty() {
        return Mono.justOrEmpty("this si test.");
    }

    /**
     * 创建一个只包含错误消息的序列。
     * @return Mono
     */
    @GetMapping("/e/error")
    public Mono<Object> error() {
        return Mono.fromCallable(() -> {
            var a = true;
            if (a) {
                return Mono.error(RuntimeException::new);
            }
            return "callable run ";
        });
    }

    /**
     * 创建一个不包含任何消息通知的序列。
     * 会一直阻塞用户的请求。因为一直没有返回 序列结束的消息通知。
     * @return Mono
     */
    @GetMapping("/e/never")
    public Mono<String> never() {
        return Mono.never();
    }

    // ---------------------------mono 静态（写死）的常规操作---------------------------------------------

    /**
     * 创建一个不包含任何消息通知的序列。
     * 会一直阻塞用户的请求。因为一直没有返回 序列结束的消息通知。
     * @return Mono
     */
    @GetMapping("/e/create")
    public Mono<String> create() {
        return Mono.create(stringMonoSink -> {

            // 请求过来了，就调用该函数
            stringMonoSink.onRequest(value -> System.out.println(String.format("请求接收到了，序列号为%s",value)));
            // 如果请求被取消，就调用该函数
            stringMonoSink.onCancel(() -> System.out.println("请求取消了"));
            // 如果请求被销毁，就调用该函数
            stringMonoSink.onDispose(() -> System.out.println("请求销毁了"));

//             发布结束（成功）序列
            stringMonoSink.success();

            // 发布结束（异常）序列
//            stringMonoSink.error(new RuntimeException("this is error"));
        });
    }

    @GetMapping("/f/from")
    public Mono from() {
        return Mono.from(s -> {
            // 发布结束（成功）信息
//            s.onComplete();

            // 发布结束（异常）信息
//            s.onError(new RuntimeException("this is error"));

            // 分发信息,
            s.onNext("s");

            // 分发订阅，请求和取消
            s.onSubscribe(new Subscription() {
                @Override
                public void request(long n) {
                    // 请求时执行
                    System.out.println("请求成功");
                }

                @Override
                public void cancel() {
                    // 取消后执行
                    System.out.println("请求取消");
                }
            });

            s.onComplete();
        });
    }





}
